package com.yonghui.springsecurityoauth2demo.config;

import cn.hutool.json.JSONUtil;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.yonghui.springsecurityoauth2demo.pojo.CustomOAuth2AccessToken;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.concurrent.TimeUnit;

public class CaffeineJwtTokenStore extends JwtTokenStore {

    private final Cache<String, OAuth2Authentication> authenticationCache;
    private final Cache<String, OAuth2AccessToken> accessTokenCache;

    public CaffeineJwtTokenStore(JwtAccessTokenConverter jwtTokenEnhancer) {
        super(jwtTokenEnhancer);

        // 初始化Caffeine缓存
        authenticationCache = Caffeine.newBuilder()
                .expireAfterWrite(60, TimeUnit.MINUTES) // 设置缓存过期时间
                .maximumSize(100000) // 设置缓存最大容量
                .build();

        accessTokenCache = Caffeine.newBuilder()
                .expireAfterWrite(60, TimeUnit.MINUTES) // 设置缓存过期时间
                .maximumSize(100000) // 设置缓存最大容量
                .build();
    }

    @Override
    public OAuth2Authentication readAuthentication(String token) {
        System.out.println(">>>>>>>>>>>>>>>调用了readAuthentication");
        OAuth2Authentication ifPresent = authenticationCache.getIfPresent(token);
        System.out.println(">>>>>>>>>>>>>>>调用了readAuthentication:"+ JSONUtil.toJsonStr(ifPresent));
        return ifPresent;
    }

    @Override
    public OAuth2AccessToken readAccessToken(String tokenValue) {
        System.out.println(">>>>>>>>>>>>>>>调用了readAccessToken");
        OAuth2AccessToken ifPresent = accessTokenCache.getIfPresent(tokenValue);
        System.out.println(">>>>>>>>>>>>>>>调用了readAccessToken:"+ JSONUtil.toJsonStr(ifPresent));
        return ifPresent;
    }

    @Override
    public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
        System.out.println(">>>>>>>>>>>>>>>调用了storeAccessToken");

        CustomOAuth2AccessToken customToken = new CustomOAuth2AccessToken(token);
        accessTokenCache.put(customToken.getValue(), customToken);
        authenticationCache.put(customToken.getValue(), authentication);
    }

    public void refreshAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
        System.out.println(">>>>>>>>>>>>>>>调用了refreshAccessToken");
        System.out.println("Token class: " + token.getClass().getName());

        if (token instanceof DefaultOAuth2AccessToken) {
            DefaultOAuth2AccessToken customToken = (DefaultOAuth2AccessToken) token;
            customToken.setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000)); // 设置新的过期时间
            accessTokenCache.put(customToken.getValue(), customToken);
            authenticationCache.put(customToken.getValue(), authentication);
        }
    }

    @Override
    public void removeAccessToken(OAuth2AccessToken token) {
        System.out.println(">>>>>>>>>>>>>>>调用了removeAccessToken");
        accessTokenCache.invalidate(token.getValue());
        authenticationCache.invalidate(token.getValue());
    }
}
